home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Visual Database / Visual BASIC 5.0 (Ent. Edition) / Vb5ent Extractor.EXE / VB / SAMPLES / ENTRPRIS / APE / AEEXPDTR / MODEXPDT.BAS < prev    next >
Encoding:
BASIC Source File  |  1996-12-06  |  19.9 KB  |  453 lines

  1. Attribute VB_Name = "modExpediter"
  2. Option Explicit
  3. '-------------------------------------------------------------------------
  4. 'The project is the Expediter component of the Application Performance Explorer
  5. 'The Expediter is a multi-use server that is instanced by the QueueMgr.
  6. 'The Expediter pulls Service Results data and Callbacks objects from
  7. 'the QueueMgr and then sends the Service Results using the Callback objects
  8. '
  9. 'Key Files:
  10. '   frmExpdt.frm    Only form in this project
  11. '   CallbkRf.cls    Class used to store callback object and related
  12. '                   Service request data
  13. '   clsPosFm.cls    Class used to store Form position in registry
  14. '   Expeditr.cls    Multi-use creatable class provides OLE interface to app
  15. '-------------------------------------------------------------------------
  16.  
  17. 'Declares
  18. Declare Function GetTickCount Lib "kernel32" () As Long
  19.  
  20. 'U/I captions resource string keys
  21. Public Const giFORM_CAPTION As Integer = 101
  22. Public Const giCURRENT_BACKLOG_CAPTION As Integer = 102
  23. Public Const giPEAK_BACKLOG_CAPTION As Integer = 103
  24. Public Const giTOTAL_CALLBACK_CAPTION As Integer = 104
  25.  
  26. 'Constants
  27. Public Const gbSHOW_FORM_DEFAULT As Boolean = False
  28. Public Const gbLOG_DEFAULT As Boolean = False
  29. Public Const glMAX_COUNT As Long = 2147483647        'max size of long data type
  30. Public Const giMAX_ALLOWED_RETRIES As Integer = 500  'maximum number of times one object can be
  31.                                                      'called with call rejection before giving up
  32. Public Const giRETRIES_ALLOWED_BEFORE_MOVING_ON = 10 'Number of retries made on a callback before
  33.                                                      'it is skipped to try again later
  34. Public Const giRETRY_WAIT_MIN As Integer = 500       'Retry Wait is measure in DoEvent cyles
  35. Public Const giRETRY_WAIT_MAX As Integer = 2500
  36. Public Const giTIMER_INTERVAL As Integer = 1000
  37.  
  38. 'Message Constants, resourse string
  39. Public Const giCALLBACK_CALLED As Integer = 4
  40. Public Const giEXPEDITER_NAME As Integer = 5
  41. Public Const giCALLING_CALLBACK As Integer = 7
  42. Public Const giSTOP_TEST_RECEIVED As Integer = 8
  43. Public Const giCALL_REJECTED_RETRIES_EXHAUSTED As Integer = 9
  44. Public Const giRETRY_CALLBACK As Integer = 10
  45. Public Const giGETRESULTS_CALLED_WITH_RETURN = 11
  46. Public Const giCOULD_NOT_FIND_SYNC_OBJECT = 12
  47. Public Const giERROR_PREFIX = 13
  48. Public Const giFONT_CHARSET_INDEX As Integer = 30
  49. Public Const giFONT_NAME_INDEX As Integer = 31
  50. Public Const giFONT_SIZE_INDEX  As Integer = 32
  51.  
  52. 'Public Variables
  53.  
  54. Public gbShow As Boolean                    'If true show form
  55. Public glInstances As Long                  'Count of created instances of Expediter Class
  56. Public gcCallBack As Collection             'Collection of CallBackRef class
  57. Public gbLog As Boolean                     'If true log Service
  58. Public goLogger As AELogger.Logger          'Logger class object
  59. Public goQueueDelegator As APEInterfaces.QueueDelegator 'QueueMgr object
  60. Public gbStopTest As Boolean                'Flag used to stop processing
  61. Public glBacklog As Long                    'The current number of Callbacks ready to be called
  62. Public glPeakBacklog As Long                'The largest that of Callbacks that were ready to be
  63.                                             'called has been as once
  64. Public glTotalCallBacks As Long             'The total number of Callbacks made
  65. Public gbBusy As Boolean                    'If true in frmExpediter.tmrExpediter.Timer event
  66. Public gbUnloading As Boolean               'If true Class_Terminate of Expediter has been entered
  67.  
  68. Sub Main()
  69. End Sub
  70.  
  71. Public Function PollQueue() As Boolean
  72.     '-------------------------------------------------------------------------
  73.     'Purpose:   Get Service Results and corresponding Callback objects from the
  74.     '           QueueMgr
  75.     'Return:    True if one or more Service Result was received from the QueueMgr
  76.     'Assumes:
  77.     '   [goQueueDelegator]
  78.     '           is a valid AEQueueMgr.QueueDelegator object
  79.     '   [gcCallback]
  80.     '           is a valid collection object
  81.     'Effects:
  82.     '   [gcCallback]
  83.     '           A CallBkRf object will be added for every Service Result received
  84.     '           from the QueueMgr.
  85.     '-------------------------------------------------------------------------
  86.     Dim vaResults As Variant    'Variant array that will be received from call
  87.                                 'to the QueueMgr.  Two dimensions: first dimension
  88.                                 'is fixed each index representing a Service Result
  89.                                 'element; the second dimension each index represents
  90.                                 'one Service result.  See index constants in
  91.                                 'modAEConstants
  92.     Dim lCount As Long          'Counter used to loop through indexes of the
  93.                                 'arrays second dimension
  94.     Dim oCallBkRef As CallBackRef   'Object to store service results in and add
  95.                                     'to gcCallback
  96.     Dim bReturn As Boolean          'Value to be returned by this function
  97.     Dim lUB As Long             'Ubound
  98.     
  99.     On Error GoTo PollQueueError
  100.     bReturn = False
  101.     
  102.     'Call the QueueMgr
  103.     vaResults = goQueueDelegator.GetServiceResults
  104.     
  105.     'Check to see if results were returned
  106.     If VarType(vaResults) = vbArray + vbVariant Then
  107.         'Results were returned
  108.         bReturn = True
  109.         LogEvent giGETRESULTS_CALLED_WITH_RETURN, 0
  110.         'Put each service result in a CallBackRef object
  111.         'and at it to the gcCallback collection
  112.         lUB = UBound(vaResults, 2)
  113.         For lCount = 0 To lUB
  114.             Set oCallBkRef = New CallBackRef
  115.             With oCallBkRef
  116.                 .ServiceID = vaResults(giRESULT_ID_ELEMENT, lCount)
  117.                 If vaResults(giRESULT_CALLBACK_TYPE_ELEMENT, lCount) = giRETURN_BY_SYNC_EVENT Then
  118.                     .UseSyncEvent = True
  119.                     Set .SyncObject = vaResults(giRESULT_CALLBACK_ELEMENT, lCount)
  120.                 Else
  121.                     .UseSyncEvent = False
  122.                     Set .Object = vaResults(giRESULT_CALLBACK_ELEMENT, lCount)
  123.                 End If
  124.                 .Error = vaResults(giRESULT_ERROR_ELEMENT, lCount)
  125.                 'Check what data type the data element is
  126.                 'in order to determine how to handle it
  127.                 Select Case VarType(vaResults(giRESULT_DATA_ELEMENT, lCount))
  128.                     Case vbEmpty, vbNull
  129.                         .Result = Null
  130.                     Case vbObject, vbError, vbDataObject
  131.                         Set .Result = vaResults(giRESULT_DATA_ELEMENT, lCount)
  132.                     Case Else
  133.                         .Result = vaResults(giRESULT_DATA_ELEMENT, lCount)
  134.                 End Select
  135.             End With
  136.             gcCallBack.Add oCallBkRef
  137.             Set oCallBkRef = Nothing
  138.         Next
  139.         'Update Expediter U/I
  140.         glBacklog = glBacklog + lUB + 1
  141.         If glBacklog > glPeakBacklog Then
  142.             glPeakBacklog = glBacklog
  143.         End If
  144.         If gbShow Then
  145.             With frmExpediter
  146.                 .lblBacklog.Caption = glBacklog
  147.                 .lblPeak = glPeakBacklog
  148.                 .lblBacklog.Refresh
  149.                 .lblPeak.Refresh
  150.             End With
  151.         End If
  152.     End If
  153.     PollQueue = bReturn
  154.     Exit Function
  155. PollQueueError:
  156.     Dim iRetry As Integer
  157.     Dim il As Integer
  158.     Dim ir As Integer
  159.     Select Case Err.Number
  160.         Case RPC_E_CALL_REJECTED
  161.             'Collision error, the OLE server is busy
  162.             'First check for stop test
  163.             If gbStopTest Then Exit Function
  164.             If iRetry < giRETRIES_ALLOWED_BEFORE_MOVING_ON Then
  165.                 iRetry = iRetry + 1
  166.                 ir = Int((giRETRY_WAIT_MAX - giRETRY_WAIT_MIN + 1) * Rnd + giRETRY_WAIT_MIN)
  167.                 For il = 0 To ir
  168.                     DoEvents
  169.                     If gbStopTest Then Exit For
  170.                 Next il
  171.                 'Stop test may have been called during doevents loop
  172.                 If gbStopTest Then Exit Function Else Resume
  173.             End If
  174.         Case Else
  175.             LogError Err, 0
  176.     End Select
  177.     PollQueue = bReturn
  178. End Function
  179.  
  180. Public Sub DeliverResults()
  181.     '-------------------------------------------------------------------------
  182.     'Purpose:   Try to make calls to Callback objects, to deliver Service Results
  183.     '           to the corresponding Callback objects.  After all callback are
  184.     '           at least attempted to be called, call PollQueue to get more
  185.     '           Service Results.  Try to make calls to all the new Callback
  186.     '           objects.  Continue cycle until the QueueMgr does not return
  187.     '           new Service Results.  If the cycle is broken because the QueueMgr
  188.     '           did not return Service Results, start the timer so that it
  189.     '           will poll the QueueMgr until ServiceResults are obtained
  190.     'Assumes:
  191.     '   [gcCallback]
  192.     '           is a valid collection object
  193.     '   [oCallBkRf.Object]
  194.     '           has a valid Callback method
  195.     'Effects:
  196.     '   [gcCallback]
  197.     '           Is decreased by one CallBkRf object every time a callback is
  198.     '           successfully made.
  199.     '           After polling the QueueMgr the count will increment for every
  200.     '           received Service Result.
  201.     '-------------------------------------------------------------------------
  202.     Dim oCallBkRf As CallBackRef    'Object for storing Service Result data and
  203.                                     'its callback
  204.     Dim lCurrentIndex As Long       'Index of oCallBkRf in gcCallBack currently
  205.                                     'being processed
  206.     Dim lCurrentID As Long          'Current Service ID being processed
  207.                                     'used for reporting and logging errors
  208.     Dim bResult As Boolean          'Result from Calling PollQueue
  209.     Dim iRetry As Integer           'Number of retries made to call a specific
  210.                                     'object using a resume statement
  211.     On Error GoTo DeliverResultsError
  212.     lCurrentIndex = 1
  213.     
  214. TryNextCallback:
  215.     Do While lCurrentIndex <= gcCallBack.Count And Not gbStopTest
  216.         Set oCallBkRf = gcCallBack.Item(lCurrentIndex)
  217.         lCurrentID = oCallBkRf.ServiceID
  218.         'Call Callback object
  219.         LogEvent giCALLING_CALLBACK, lCurrentID
  220.         iRetry = 0
  221.         If oCallBkRf.UseSyncEvent Then
  222.             oCallBkRf.SyncObject.RaiseServiceResult lCurrentID, oCallBkRf.Result, oCallBkRf.Error
  223.         Else
  224.             oCallBkRf.Object.CallBack lCurrentID, oCallBkRf.Result, oCallBkRf.Error
  225.         End If
  226.         LogEvent giCALLBACK_CALLED, lCurrentID
  227.         'Explicitely set callback object to nothing
  228.         Set oCallBkRf.Object = Nothing
  229.         Set gcCallBack.Item(lCurrentIndex).Object = Nothing
  230.         gcCallBack.Remove lCurrentIndex
  231.         
  232.         'Update Expediter U/I
  233.         glBacklog = glBacklog - 1
  234.         glTotalCallBacks = glTotalCallBacks + 1
  235.         If gbShow Then
  236.             With frmExpediter
  237.                 .lblBacklog.Caption = glBacklog
  238.                 .lblCount.Caption = glTotalCallBacks
  239.                 .lblBacklog.Refresh
  240.                 .lblCount.Refresh
  241.             End With
  242.         End If
  243.             
  244.         'Loop without iterating lCurrentIndex because the lCurrentIndex item
  245.         'will be replaced by one above it after it is removed.
  246.         'lCurrentIndex is only iterated by Error Handling, which will move
  247.         'the process on to another callback after a few retries.
  248.     Loop
  249.     
  250.     'After going through the whole gcCallBack collection
  251.     'Poll the queuemgr trying to get more ServiceResults
  252.     'Go back to the top of the Loop using index 1 if
  253.     'there are items in gcCallBack after Polling the QueueMgr
  254.     bResult = PollQueue
  255.     lCurrentIndex = 1
  256.     'Got to top of loop if there are any items in gcCallBack
  257.     'Do not use the result of the PollQueue function because
  258.     'even if the QueueMgr did not return results there may
  259.     'be items in gcCallBack representing exhausted Callbacks
  260.     'that need to be tried again.
  261.     If gcCallBack.Count > 0 And Not gbStopTest Then GoTo TryNextCallback
  262.     
  263.     'Before exiting the function start the timer
  264.     'so that the Expediter will keep polling the QueueMgr
  265.     frmExpediter.tmrExpediter.Interval = giTIMER_INTERVAL
  266.     Exit Sub
  267.  
  268. DeliverResultsError:
  269.     Dim il As Integer
  270.     Dim ir As Integer
  271.     Select Case Err.Number
  272.         Case RPC_E_CALL_REJECTED
  273.                'Collision error, the OLE server is busy
  274.                'First check for stop test
  275.                If gbStopTest Then Exit Sub
  276.                If iRetry < giRETRIES_ALLOWED_BEFORE_MOVING_ON Then
  277.                    'Iterate the object's retry count
  278.                    oCallBkRf.CallAttempts = oCallBkRf.CallAttempts + 1
  279.                    'Iterate the number of try's make with Resume
  280.                    iRetry = iRetry + 1
  281.                    ir = Int((giRETRY_WAIT_MAX - giRETRY_WAIT_MIN + 1) * Rnd + giRETRY_WAIT_MIN)
  282.                    For il = 0 To ir
  283.                        DoEvents
  284.                    Next il
  285.                    LogEvent giRETRY_CALLBACK, lCurrentID
  286.                    Resume
  287.                Else
  288.                     'We reached our max retries either move on
  289.                     'to the next object in the collection leaving this
  290.                     'object to be tried again later or remove the object
  291.                     'because this object was had too many callattempts on
  292.                     'it specifically.
  293.                     If oCallBkRf.CallAttempts >= giMAX_ALLOWED_RETRIES Then
  294.                         'Give up trying to call this particulary object
  295.                         'it will be removed at the end of Select Case block
  296.                         'Since it is being removed do not iterate the lCurrenIndex
  297.                         LogEvent giCALL_REJECTED_RETRIES_EXHAUSTED, lCurrentID
  298.                         DisplayStatus LoadResString(giCALL_REJECTED_RETRIES_EXHAUSTED)
  299.                     Else
  300.                         'Iterate the lCurrentIndex and do not remove this
  301.                         'object.  It will be reattempted later
  302.                         lCurrentIndex = lCurrentIndex + 1
  303.                         Resume TryNextCallback
  304.                     End If
  305.                End If
  306.         Case ERR_OVER_FLOW
  307.             glTotalCallBacks = 0
  308.             LogError Err, lCurrentID
  309.             Resume Next
  310.         Case ERR_CALL_FAILED_DIDNOT_EXECUTE
  311.             LogError Err, lCurrentID
  312.         Case Else
  313.             LogError Err, lCurrentID
  314.     End Select
  315.     On Error Resume Next
  316.     'Explicitely set callback object to nothing
  317.     Set oCallBkRf.Object = Nothing
  318.     Set gcCallBack.Item(lCurrentIndex).Object = Nothing
  319.     gcCallBack.Remove lCurrentIndex
  320.     Exit Sub
  321. End Sub
  322.  
  323. Public Sub LogEvent(intMessage As Integer, lServiceID As Long)
  324.     '-------------------------------------------------------------------------
  325.     'Purpose:   Receives Message key which is used to look
  326.     '           up a resource string.  The logrecord is sent to the
  327.     '           Logger object if gbLog is true
  328.     'In:        [intMessage]
  329.     '               A valid Resource string key for the message to be logged
  330.     '           [lServiceID]
  331.     '               Service Request ID to be logged
  332.     'Assumption:
  333.     '           If gbLog is true then goLogger is a valid reference to
  334.     '           AELogger.Logger class object
  335.     '-------------------------------------------------------------------------
  336.     
  337.     On Error GoTo LogEventError
  338.     If gbLog And Not gbStopTest Then
  339.         goLogger.Record LoadResString(giEXPEDITER_NAME), lServiceID, LoadResString(intMessage), GetTickCount()
  340.     End If
  341.     'If the form is visible display log on form
  342.     #If ccShowList Then
  343.         DisplayString CStr(lServiceID) & gsSEPERATOR & LoadResString(intMessage)
  344.     #End If
  345.     Exit Sub
  346. LogEventError:
  347.     Select Case Err.Number
  348.         Case RPC_E_CALL_REJECTED
  349.                'Collision error, the OLE server is busy
  350.                Dim iRetry As Integer
  351.                Dim il As Integer
  352.                Dim ir As Integer
  353.                If iRetry < giMAX_ALLOWED_RETRIES Then
  354.                    iRetry = iRetry + 1
  355.                    ir = Int((giRETRY_WAIT_MAX - giRETRY_WAIT_MIN + 1) * Rnd + giRETRY_WAIT_MIN)
  356.                    For il = 0 To ir
  357.                        DoEvents
  358.                    Next il
  359.                    Resume
  360.                Else
  361.                    'We reached our max retries
  362.                    'This would occur when clients are sending
  363.                    'there logs
  364.                    LogError Err, lServiceID
  365.                    Exit Sub
  366.                End If
  367.         Case Else
  368.             LogError Err, lServiceID
  369.             Exit Sub
  370.     End Select
  371.     Exit Sub
  372. End Sub
  373.  
  374. Public Sub LogError(ByVal oErr As ErrObject, lServiceID As Long)
  375.     '-------------------------------------------------------------------------
  376.     'Purpose:   Display error description on forms Status box if the form is
  377.     '           visible; log error if logging is on
  378.     'In:        [oErr]
  379.     '               Valid error object
  380.     '           [lServiceID]
  381.     '               Service Request ID logged with the error message
  382.     'Assumption:
  383.     '           If gbShow is true the form is loaded and visible
  384.     '           If gbLog is true the goLogger is a valid AELogger.Logger class
  385.     '               object
  386.     '-------------------------------------------------------------------------
  387.     
  388.     Dim s As String
  389.     s = LoadResString(giERROR_PREFIX) & Str$(oErr.Number) & gsSEPERATOR & oErr.Source & gsSEPERATOR & oErr.Description
  390.     #If ccShowList Then
  391.         If Not gbShow Then
  392.             frmExpediter.Show
  393.             gbShow = True
  394.         End If
  395.         DisplayString s
  396.     #Else
  397.         If Err.Number <> 0 Then DisplayStatus oErr.Description
  398.     #End If
  399.     If gbLog And glInstances <> 0 Then
  400.         goLogger.Record LoadResString(giEXPEDITER_NAME), lServiceID, s, GetTickCount()
  401.     End If
  402.     Exit Sub
  403. End Sub
  404.  
  405. Sub DisplayStatus(s As String)
  406.     '-------------------------------------------------------------------------
  407.     'Purpose:   If gbShow is true, displays passed string on forms status box
  408.     'Assumes:   If gbShow is true, form is loaded and visible
  409.     '-------------------------------------------------------------------------
  410.     If gbShow Then frmExpediter.lblStatus = s
  411. End Sub
  412.  
  413. Sub DisplayString(sText As String)
  414.     '-------------------------------------------------------------------------
  415.     'Purpose:   Adds the passed text to to the list box.  Only used if conditional
  416.     '           compile ccShowList is true.
  417.     'Assumes:   If gbShow is true, form is visible
  418.     '           If ccShowList is true, lstLog is visible and positioned
  419.     '-------------------------------------------------------------------------
  420.     'Controls the length of the list box
  421.     'and adds items to the top
  422.     #If ccShowList Then
  423.         Dim lstLog As ListBox
  424.         If gbShow Then
  425.             Set lstLog = frmExpediter.lstLog
  426.             If lstLog.ListCount = glLIST_BOX_MAX Then lstLog.Clear
  427.             lstLog.AddItem sText, 0
  428.             DoEvents
  429.         End If
  430.     #End If
  431. End Sub
  432.  
  433. Sub DestroyReferences()
  434.     '-------------------------------------------------------------------------
  435.     'Purpose:   Called by in the event of a StopTest call
  436.     '           to destroy callback objects
  437.     '-------------------------------------------------------------------------
  438.     
  439.     Dim oCallback As CallBackRef
  440.     LogEvent giSTOP_TEST_RECEIVED, 0
  441.     frmExpediter.tmrExpediter.Interval = 0
  442.     For Each oCallback In gcCallBack
  443.         Set oCallback.Object = Nothing
  444.     Next
  445.     Set gcCallBack = Nothing
  446.     Set gcCallBack = New Collection
  447.     Set goQueueDelegator = Nothing
  448.     If gbUnloading Then
  449.         If gbLog Then Set goLogger = Nothing
  450.         Unload frmExpediter
  451.     End If
  452. End Sub
  453.